<?php
declare(strict_types=1);

namespace App\Wxc\Service;

use App\Wxc\Concern\ManageChannelsShopApp;
use App\Wxc\Model\WxcShopCallback;
use Closure;
use Deepwell\ChannelsShop\Api\Sharer\Event\Payload\SharerChange;
use Deepwell\ChannelsShop\Config;
use Deepwell\EasyQuery\Concern\QueryService;
use EasyWeChat\OfficialAccount\Message;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Mine\Exception\MineException;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
use Throwable;

/**
 * 微信小店回调消息处理服务
 */
class WxcShopCallbackService
{
    use ManageChannelsShopApp;
    use QueryService;

    #[Inject]
    private EventDispatcherInterface $eventDispatcher;

    public function __construct()
    {
        $this->queryModelClassName = WxcShopCallback::class;
    }

    /**
     * 处理小店消息回调
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws Throwable
     */
    public function serve(RequestInterface $request): ResponseInterface
    {
        // 根据appid获取小店配置
        $appId = $request->query('app_id');
        $app = $this->initApplicationByAppId($appId);
        $app->setRequest($request);
        $server = $app->getServer();

        // 保存请求
        $get = $request->getQueryParams();
        $post = $request->getParsedBody();

        $record = [
            'content' => [
                'get' => $get,
                'post' => $post,
            ]
        ];
        $callbackRecord = WxcShopCallback::create($record);
        $rid = $callbackRecord->id;

        $server->with(function (Message $message, Closure $next) use ($appId, $rid) {
            call_user_func_array([$this, 'handle'], [$message, $appId, $rid]);
            return $next($message);
        });

        return $server->serve();
    }

    protected function handle(Message $message, string $appId, int $rid)
    {
        $callback = WxcShopCallback::find($rid);
        $data = $message->toArray();
        $data['app_id'] = $appId;
        switch ($message->Event) {
            case 'channels_ec_sharer_change':
                container()->get(WxcSharerService::class)->handleChange(SharerChange::from($data));
                break;
        }
        $callback->status = 200;
        $callback->save();
    }
}